import * as express from 'express'
import * as bodyParser from 'body-parser'
import {
  Claim,
  DDO,
  Identity,
  Wallet,
  Account,
  Crypto,
  Transaction,
  TransactionBuilder,
  OntidContract,
  RestClient,
  CONST
} from 'ontology-ts-sdk';
import * as walletJson from './wallet'

interface ScryptParams {
    cost: number;
    blockSize: number;
    parallel: number;
    size: number;
}

class App {
  public express

  constructor () {
    this.express = express()
    this.mountRoutes()
  }

  private mountRoutes (): void {
    const router = express.Router()
    const DEFAULT_SCRYPT = {
      cost: 4096,
      blockSize: 8,
      parallel: 8,
      size: 64
    }
    const mnemonic = "cover tone pact voice neglect fiscal make notice recipe purchase buyer once"
    const privateKey = Crypto.PrivateKey.generateFromMnemonic(mnemonic)
    const publicKey = privateKey.getPublicKey();
    const password = "12345678"
    const label = "dontor"
    const accountLabel = "dontorAccount"
    const name = "Max Luk"
    const account = Account.importWithMnemonic(accountLabel, mnemonic, password, DEFAULT_SCRYPT)
    const identity = Identity.create(privateKey, password, label)
    const did = identity.ontid;
    const gasPrice = '500';
    const gasLimit = '20000';
    // wallet.addAccount(account)
    router.use(bodyParser.json())
    router.get('/', (req, res) => {
      console.log('walletJson =', walletJson)
      // const wallet = Wallet.create('dontor_wallet');
      const wallet = Wallet.fromWalletFile(walletJson)
      console.log('wallet =', wallet)
      const rprivateKey = Crypto.PrivateKey.random()

      // wallet related
      console.log('========================')
      console.log('wallet.account', wallet.accounts)
      console.log('========================')
      console.log('account', account)
      console.log('========================')

      const identity = Identity.create(rprivateKey, password, label)

      //suppose we already got a identity
      const did = identity.ontid;
      console.log(did)

      //we need the public key, which can be generate from private key
      // const pk = privateKey.getPublicKey();
      // const gasPrice = '500';
      // const gasLimit = '20000';
      const tx = OntidContract.buildRegisterOntidTx(did, publicKey, gasPrice, gasLimit);
      //we also need an account to pay for the gas
      //supporse we have an account and the privateKey
      // sign transaction with payer account address
      tx.payer = account.address
      //Then sign the transaction with payer's account
      //we already got transaction created before,add the signature.
      TransactionBuilder.addSign(tx, privateKey)
      // TransactionBuilder.signTransaction(tx, privateKey);

      const rest = new RestClient(CONST.TEST_ONT_URL.REST_URL);
      rest.sendRawTransaction(tx.serialize()).then(res => {
          console.log(res)
      })

      const result = {
        wallet,
        walletAccount: wallet.accounts,
        privateKey,
        identity,
        tx
      }
      console.log('result =', result)
      wallet.setDefaultAccount('AVEhhksQkU772qcR49D5r81ibUsN8fUWHb')
      res.json(result)
    })
    router.get('/patient', (req, res, next) => {
      const ontid = req.query.ontid
      const tx = OntidContract.buildGetDDOTx(ontid)
      const rest = new RestClient();
      rest.sendRawTransaction(tx.serialize(), true).then(response => {
        console.log(response);
        console.log(response.Result);
        const resultDDO = response.Result.Result
        console.log(resultDDO);

        const parsed = DDO(resultDDO)
        console.log('parsed =', parsed);

        // const deserialized = response.Result.Result.deserialize()
        return res.json({
          ontid,
          response
        })
      })
    })

    router.post('/patient', (req, res, next) => {
      const signature = null;
      const useProof = false;
      const currentTimestamp = Math.round(new Date().getTime()/1000.0)

      const url = 'http://polaris1.ont.io:20335'
      // const payer = new Crypto.Address('AVEhhksQkU772qcR49D5r81ibUsN8fUWHb')
      const payer = account.address
      const patientPrivateKey = Crypto.PrivateKey.random()
      const patientPublicKey = patientPrivateKey.getPublicKey();
      const patientLabel = `patient_${patientPublicKey.key}`
      const patientIdentity = Identity.create(patientPrivateKey, password, patientLabel)
      const patientOntid = patientIdentity.ontid;
      console.log('patientPublicKey =', patientPublicKey)

      const tx = OntidContract.buildRegisterOntidTx(patientOntid, publicKey, gasPrice, gasLimit);
      tx.payer = account.address
      TransactionBuilder.addSign(tx, privateKey)

      const rest = new RestClient(CONST.TEST_ONT_URL.REST_URL);

      rest.sendRawTransaction(tx.serialize())
        .then(response => {
          if (response.Error) {
            return res.json(response)
          }
          console.log('register response =', response)
          const claim = new Claim({
              messageId: patientLabel,
              issuer: did,
              subject: patientOntid,
              issuedAt: currentTimestamp
          }, signature, useProof);

          claim.version = '0.7.0';
          claim.context = 'https://example.com/template/v1';
          claim.content = {
            Name: req.body.name,
            Gender: req.body.gender,
            Country: req.body.country
          };
          console.log('claim =', claim)
          claim.attest(url, gasPrice, gasLimit, payer, privateKey).then(result => {
              console.log('claim result =', result)
              res.json({
                ontid: patientOntid,
                publicKey: patientPublicKey,
                response,
                claim: result
              })
          })
          .catch(err => {
            console.log('claim.attest error =', err)
          })
          // res.json({
          //   ontid: patientOntid,
          //   response,
          //   result
          // })
        })
    })
    router.get('/patient_status', (req, res, next) => {
      const url = 'http://polaris1.ont.io:20335'
      const patientPublicKeyId = req.query.public_key_id
      // const patientData = new Claim.GetStatusResponse
      // Claim.serializeUnsigned()
      // Claim.retrievePublicKey(patientPublicKeyId, url)
      //   .then(publicKey => {
      //     console.log('publicKey =', publicKey)
      //   })

    })
    this.express.use('/', router)
  }
}

export default new App().express
